package com.github.yeecode.mybatisdemo.xml;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.parsing.XNode;
import org.apache.ibatis.parsing.XPathParser;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * 模仿mybatis 去访问 mapper
 */
public class XmlDemo {

    static String UserMapper_xml = "com/github/yeecode/mybatisdemo/mapper/UserMapper.xml";
    static String mybatis_config_xml = "mybatis-config.xml";
    static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    static InputStream mapperInputStream;


    static DocumentBuilder documentBuilder;

    static {
        try {
            documentBuilder = factory.newDocumentBuilder();
            mapperInputStream = Resources.getResourceAsStream(UserMapper_xml);
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void parseXml() throws IOException, SAXException {
        // 得到配置文件的输入流
        InputStream inputStream = Resources.getResourceAsStream(UserMapper_xml);

        documentBuilder.setEntityResolver(new DomEntityResolver());
        // documentBuilder.parse(DOMParser.class.getClassLoader().getResource("").getFile());
        Document doc = documentBuilder.parse(inputStream);  //通过流来获得 xml配置
        Element root = doc.getDocumentElement();
        System.out.println(" 根节点 root node ==>  " + root.getNodeName()); // mapper
        System.out.println("递归解析--------------begin------------------");
        // 递归解析Element
        parseElement(root);
        System.out.println("递归解析--------------end------------------");

    }


    public static void parseMapperXml() throws IOException, ParserConfigurationException, SAXException {
        // 得到配置文件的输入流


        documentBuilder.setEntityResolver(new DomEntityResolver());
        Document doc = documentBuilder.parse(mapperInputStream);


        //解析public id 和system id ???

        XPathParser xPathParser = new XPathParser(doc);

        List<XNode> xNodes = xPathParser.evalNodes("/mapper/select");
        // System.out.println("xNodes.toString() = =====================> " + xNodes.toString());

        XNode xNode1 = xPathParser.evalNode("/mapper/*[1]");  //第一个 select 元素

        System.out.println("xNode.getStringAttribute(\"id\", \"id\") = " + xNode1.getStringAttribute("id", "id"));


        for (XNode xNode : xNodes) {
            System.out.println("xNode.getStringBody() = " + xNode.getStringBody());
            System.out.println("xNode.toString() =========> \n " + xNode.toString());

            System.out.println("-----------------------------------");
/*            System.out.println("节点名称: " + xNode.getName() + "  节点路径: " + xNode.getPath() + "   节点字符串: " + xNode.getStringBody()

                    + "节点类型: " + xNode.getNode().getNodeType() + " end");*/
        }


    }


    public static void parseResultType() throws IOException, SAXException {

        documentBuilder.setEntityResolver(new DomEntityResolver());
        Document doc = documentBuilder.parse(mapperInputStream);
        XPathParser xPathParser = new XPathParser(doc);
        XNode resultMapNode = xPathParser.evalNode("/mapper/resultMap");  //第一个 select 元素  "/mapper/resultMap"

        String javaType = resultMapNode.getStringAttribute("javaType");
        String resultType = resultMapNode.getStringAttribute("resultType", javaType);
        String ofType = resultMapNode.getStringAttribute("ofType", resultType);
        String type = resultMapNode.getStringAttribute("type",ofType );
        System.out.println("type = " + type);

    }


    public static void parseConfigXml() throws IOException, SAXException {

        InputStream inputStream = Resources.getResourceAsStream(mybatis_config_xml);


        Document doc = documentBuilder.parse(inputStream);
        XPathParser xPathParser = new XPathParser(doc);

        List<XNode> xNodes = xPathParser.evalNodes("/configuration/environments");

        for (XNode xNode : xNodes) {

            System.out.println("节点名称: " + xNode.getName() + "  节点路径: " + xNode.getPath() +
                    "   节点字符串: " + xNode.getStringBody() + "节点类型:   "
                    + xNode.getNode().getNodeType() + "     ;  default属性==> " + xNode.getStringAttribute("default") +
                    "  子节点 : " + xNode.getChildren().toString() + " end");
        }

    }


    public static void main(String[] args) throws InterruptedException, ParserConfigurationException, IOException, SAXException {

        parseResultType();
    }


    //递归解析方法
    public static void parseElement(Element element) {

        System.out.print("<" + element.getTagName());
        NamedNodeMap attris = element.getAttributes();
        for (int i = 0; i < attris.getLength(); i++) {
            // 属性可是有很多个的, 例如 < a href= "" class =""  style=""></>
            Attr attr = (Attr) attris.item(i);
            System.out.print(" " + attr.getName() + "=\"" + attr.getValue() + "\"");
        }
        System.out.println(">");
        System.out.println(" 内容 ==> " + element.getTextContent() + "<== ");
        NodeList nodeList = element.getChildNodes();
        Node childNode;
        for (int temp = 0; temp < nodeList.getLength(); temp++) {
            childNode = nodeList.item(temp);

            // 判断是否属于节点
            if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                // 判断是否还有子节点
                if (childNode.hasChildNodes()) {
                    //继续解析
                    /*if (childNode.getTextContent()!= null){
                        System.out.println(" 内容 ==> "+childNode.getTextContent() + "<== ");
                    }*/
                    parseElement((Element) childNode);
                }
            }
        }
        System.out.println("</" + element.getTagName() + ">");
    }
}
